package com.xxx.exchange;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * Rabbit MQ使用场景三：发布/订阅——广播模式发布消息
 * 	1、1个生产者，多个消费者
	2、每一个消费者都有自己的一个队列
	3、生产者没有将消息直接发送到队列，而是发送到了交换机
	4、每个队列都要绑定到交换机
	5、生产者发送的消息，经过交换机，到达队列，实现，一个消息被多个消费者获取的目的
	注意：一个消费者队列可以有多个消费者实例，只有其中一个消费者实例会消费
	
	RabbitMQ提供了四种Exchange: fanout,direct,topic,header
	性能排序：fanout > direct >> topic。比例大约为11：10：6
		fanout： 即发布/订阅模式，路由规则非常简单，它会把所有发送到fanout Exchange的消息都会被转发到与该Exchange 绑定(Binding)的所有Queue上。
		direct： 默认，路由规则也很简单，它会把消息路由到那些binding key与routing key完全匹配的Queue中。
		topic：   即匹配/订阅模式，在匹配规则上进行了扩展，它与direct类型的Exchage相似，也是将消息路由到binding key与routing key相匹配的Queue中，
				但这里的匹配规则有些不同，它约定：
					a)、routing key为一个句点号“. ”分隔的字符串（我们将被句点号“. ”分隔开的每一段独立的字符串称为一个单词），如“stock.usd.nyse”、“nyse.vmw”、“quick.orange.rabbit”
					b)、binding key与routing key一样也是句点号“. ”分隔的字符串
					c)、binding key中可以存在两种特殊字符“”与“#”，用于做模糊匹配，其中“”用于匹配一个单词，“#”用于匹配多个单词（可以是零个）
		headers：基本不用， 不依赖于routing key与binding key的匹配规则来路由消息，而是根据发送的消息内容中的headers属性进行匹配。
				在绑定Queue与Exchange时指定一组键值对；当消息发送到Exchange时，RabbitMQ会取到该消息的headers（也是一个键值对的形式），
				对比其中的键值对是否完全匹配Queue与Exchange绑定时指定的键值对；如果完全匹配则消息会路由到该Queue，否则不会路由到该Queue。
 * 
 * @author guweiqiang
 * 2018年6月13日
 */
public class Publisher {
	
	private static final String EXCHANGE_NAME = "test_exchanger";
	
//	private static final String HOST = "localhost";

	public static void main(String[] args) throws IOException, TimeoutException {
		// 1.创建连接工厂，并设置工厂相关属性
		ConnectionFactory factory = new ConnectionFactory();
//		factory.setHost(HOST); // 默认为localhost
		
		// 2.创建一个连接
		Connection connection = factory.newConnection();
		
		// 3.创建一个通道
		Channel channel = connection.createChannel();
		
		// 4.声明一个交换机exchanger
		channel.exchangeDeclare(EXCHANGE_NAME, "fanout");  // type=fanout，publisher和subscibler必须要一致
		// fanout 广播是式交换器，不管消息的ROUTING_KEY设置为什么，Exchange都会将消息转发给所有绑定的Queue。
		// RabbitMQ提供了四种Exchange: fanout,direct,topic,header
		// 性能排序：fanout > direct >> topic。比例大约为11：10：6

		// 5.往队列里发送消息
		// 注意：消息发送到没有队列绑定的交换机时，消息将丢失，因为交换机没有存储消息的能力，消息只能存在在队列中。
		for(int i=1; i<=20; i++) {
			String message = "hello rabbit mq" + i;
			// 发布消息
			channel.basicPublish(EXCHANGE_NAME, "", null, message.getBytes("UTF-8"));
			// 第一个参数为交换机名称
			// 第二个参数为队列映射的路由key（这里设置为空）
			// 第三个参数为消息的其他属性
			// 第四个参数为发送信息的主体
			System.out.println("Publisher send message：" + message);
		}
		
		// 6.关闭连接
//		channel.close();
//      connection.close();
	}

}
